# 假设 Player, Deck, TurnResolver 类已分别定义在相应模块中
from entity.player import Player
from entity.deck import Deck
from entity.card import Card

class Game:
    def __init__(self, player_name="Default Player"):
        """
        初始化一局游戏：
          - 创建一个玩家对象；
          - 创建一个新牌堆对象；
          - 创建当前回合的结算器（TurnResolver），它负责处理玩家与牌堆之间的交互。
        """
        self.player = Player(player_name)
        self.deck = Deck()        
        
        # 给玩家发起始手牌
        self.player.draw_cards(self.deck.draw_initial_hand())
        
        # 游戏开始
        self.next_turn()

    def next_turn(self):
        """
        开启下一回合：
          - 重新创建一个新的 TurnResolver 对象，
            用于处理新的回合中的玩家操作和结算。
        """
        self.turn_resolver = TurnResolver(self.player, self.deck)



ILLEGAL = -1  # 用于表示结算非法

class TurnResolver:
    def __init__(self, player, deck):
        """
        初始化当前回合的结算器：
          - 保存玩家和牌堆引用；
          - 初始化结算状态：上一张牌、各牌种使用次数。
        """
        self.player = player
        self.deck = deck
        self.last_card = None  # 用于记录上一张出牌
        self.usage_counts = {
            "酒": 0,
            "闪电": 0,
            "杀": 0,
            "技能": 0
        }
    
    def clone(self):
        """
        返回当前 TurnResolver 状态的一个副本，
        便于在搜索或回溯时独立处理不同分支。
        """
        new_resolver = TurnResolver(self.player, self.deck)
        new_resolver.last_card = self.last_card  # 如需深拷贝，请使用 copy.deepcopy
        new_resolver.usage_counts = self.usage_counts.copy()
        return new_resolver
    
    def can_use_peach(self):
        """
        判断当前回合是否还能使用【桃】牌。
        此处逻辑：只要玩家当前血量低于最大血量，就可以使用【桃】牌。
        """
        return self.player.hp < self.player.max_hp

    def can_use_alcohol(self):
        """
        判断当前回合是否还能使用【酒】牌。
        此处逻辑：假设【酒】的使用次数限制为1次。
        """
        return self.usage_counts.get("酒", 0) < 1
    def can_use_lightning(self):
        """
        判断当前回合是否还能使用【闪电】牌。
        此处逻辑：假设【闪电】的使用次数限制为1次。
        """
        return self.usage_counts.get("闪电", 0) < 1

    def can_use_slash(self):
        """
        判断当前回合是否还能使用【杀】牌。
        如果玩家装备了诸葛连弩，则无限制，否则限制为2次。
        """
        if self.player.weapon is not None and self.player.weapon.name == "诸葛连弩":
            return True
        return self.usage_counts.get("杀", 0) < 2
    
    def can_use_skill(self):
        """
        判断当前回合是否可以发动【技能】：
        - 技能未使用过（使用次数少于1次）；
        - 并且必须存在上一张牌（作为技能转换的基础）。
        """
        return self.usage_counts.get("技能", 0) < 1 and self.last_card is not None

    def resolve(self, card):
        """
        结算一张卡牌：
        - 输入：当前要结算的一张 Card 对象；
        - 调用逻辑判断是否应当直接出牌或触发技能；
        - 返回结算得分（若非法则返回 ILLEGAL）。
        
        逻辑：
        1. 判断是否需要发动技能：
            1.1 对于牌名为“闪”或“借刀杀人”，直接尝试发动技能；
            1.2 对于“闪电”、“桃”、“酒”，若当前条件不满足正常使用（例如【桃】：玩家血量已满，
                【闪电】或【酒】：使用次数达到上限），则尝试发动技能；
            1.3 对于“杀”，若正常使用次数已达上限且玩家未装备诸葛连弩，则尝试发动技能；
        2. 若无需发动技能，则执行正常结算：
            - 对于有使用限制的牌（记录在 usage_counts 中），更新其使用次数；
            - 若当前牌与上一张牌在花色或点数上匹配，则得分 +1，并可触发奖励（TODO）；
            - 更新 last_card 为当前牌；
            - 如果当前牌是装备牌，则调用玩家的装备方法。
        """
        # 1. 判断是否需要发动技能
        if card.name in ["闪", "借刀杀人"]:
            return self.activate_skill(card)
        
        if card.name in ["闪电", "桃", "酒"]:
            if card.name == "桃" and not self.can_use_peach():
                return self.activate_skill(card)
            elif card.name == "闪电" and not self.can_use_lightning():
                return self.activate_skill(card)
            elif card.name == "酒" and not self.can_use_alcohol():
                return self.activate_skill(card)
        
        if card.name == "杀":
            if not self.can_use_slash():
                return self.activate_skill(card)
        
        # 2. 正常结算：更新使用次数（如果该牌有使用限制）
        if card.name in self.usage_counts:
            self.usage_counts[card.name] += 1

        # TODO  【桃】的结算是让玩家血量 + 1
        if card.name == "桃":
            self.player.hp += 1        

        score = 0
        if self.last_card is not None:
            if card.suit == self.last_card.suit or card.rank == self.last_card.rank:
                score += 1
                # TODO: 调用奖励接口，实现额外奖励逻辑
                # self.apply_reward()
        
        # 更新上一张牌
        self.last_card = card
        
        # 装备牌处理：如果当前牌为装备牌，则调用玩家的装备方法
        if card.category == "装备牌":
            self.player.equip(card)
        
        return score

    def activate_skill(self, card):
        """
        该技能发动一次的效果为：将一张当前牌 card 视为一张虚拟的基本牌使用，
        其牌面的点数保持不变，花色取自本回合上一张结算的牌。
        
        技能结算逻辑为：
        0. 若技能已发动（即当前回合已使用过【技能】）或不存在上一张牌，则直接返回 ILLEGAL；
        1. 若当前回合还能使用【桃】，则尝试包装虚拟【桃】牌进行 resolve 结算；
        2. 若仍可使用【酒】，则尝试包装虚拟【酒】牌进行 resolve 结算；
        3. 若仍可使用【杀】，则尝试包装虚拟【杀】牌进行 resolve 结算；
        若以上尝试中有一种结算成功，则记录一次技能使用并返回结算得分；若全部失败，则返回 ILLEGAL。
        """
        # 前提检查：若技能已发动或没有上一张牌，则直接返回 ILLEGAL
        if self.usage_counts.get("技能", 0) >= 1 or self.last_card is None:
            return ILLEGAL

        # 定义尝试的选项以及对应的判断条件
        options = [
            ("桃", self.can_use_peach),   # 假设 can_use_peach 已根据玩家血量进行判断
            ("酒", self.can_use_alcohol), # 假设 can_use_alcohol 根据本回合使用次数判断
            ("杀", self.can_use_slash)      # 假设 can_use_slash 根据使用次数及武器情况判断
        ]

        for option_name, can_use_fn in options:
            if can_use_fn():
                # 包装当前牌：牌面点数不变，花色取自上一张牌，名称为选项名称，类别固定为“基本牌”
                virtual_card = Card(
                    card_id=card.card_id,
                    name=option_name,
                    suit=self.last_card.suit,
                    rank=card.rank,
                    category="基本牌"
                )
                result = self.resolve(virtual_card)
                if result != ILLEGAL:
                    # 记录技能使用（这里简单加1，业务可根据需要调整）
                    self.usage_counts["技能"] = self.usage_counts.get("技能", 0) + 1
                    # print("成功使用技能：将原牌【", card, "】转化成虚拟牌【", virtual_card, "】")
                    return result
        return ILLEGAL
